import axios from "axios";
import type { AxiosRequestConfig } from "axios";
import service from "./axios";
import type { ApiResponse, ApiError } from "./types";
import { withAuthHeaders, buildAuthHeader } from "@/utils/http";

type RequestConfig = AxiosRequestConfig & {
  retry?: number; // 最大重试次数，默认 0
  retryDelay?: number; // 初始重试延迟 ms，默认 300
  retryOn?: (err: any) => boolean; // 自定义重试策略（覆盖默认）
  headers?: Record<string, any>; // 允许传入自定义头
};

// 刷新队列相关（单例）
let isRefreshing = false;
let refreshSubscribers: Array<(token: string | null) => void> = [];
function subscribeToken(cb: (token: string | null) => void) {
  refreshSubscribers.push(cb);
}
function onRefreshed(token: string | null) {
  refreshSubscribers.forEach((cb) => cb(token));
  refreshSubscribers = [];
}

function sleep(ms: number) {
  return new Promise((res) => setTimeout(res, ms));
}



// 头部工具迁移到 src/utils/http.ts 统一复用

/**
 * request wrapper
 * returns ApiResponse<T>
 */
export default async function request<T = any>(
  cfg: RequestConfig,
): Promise<ApiResponse<T>> {
  const config = { retry: 0, retryDelay: 300, ...cfg } as RequestConfig;

  // 支持 AbortSignal：axios 支持 signal 字段
  const { signal } = config as any;

  let attempt = 0;
  while (true) {
    attempt++;
    try {
  // 在每次请求前合并 headers（支持自定义 + 自动注入 token）
  Object.assign(config, withAuthHeaders(config));

      const response = await service.request<ApiResponse<T>>(config);
      const contentType = (response.headers as any)?.['content-type'] || '';
      const dataRaw: any = response.data;

      // 如果返回的是 HTML（通常是被重定向到登录页）或非对象数据，视为失败并返回规范化结果
      const isObject = dataRaw !== null && typeof dataRaw === 'object' && !Array.isArray(dataRaw);
      if (contentType.includes('text/html') || !isObject) {
        if (import.meta.env.DEV) {
          console.debug('[request] non-JSON response', {
            url: config.url,
            method: config.method,
            status: response.status,
            contentType
          })
        }
        return {
          code: response.status,
          success: false,
          message: 'Unexpected non-JSON response (possible auth redirect).',
          data: null as any,
        } as ApiResponse<T>;
      }

      // 规范化返回，兼容未提供 success/code/message 字段的后端
      const payload: any = { ...dataRaw };
      if (typeof payload.code === 'undefined') payload.code = response.status;
      if (typeof payload.success === 'undefined') {
        payload.success = payload.code === 0 || payload.code === 200 || response.status === 200;
      }
      if (typeof payload.message === 'undefined') payload.message = '';
      return payload as ApiResponse<T>;
    } catch (err: any) {
      if (import.meta.env.DEV) {
        console.debug('[request:error]', {
          url: config.url,
          method: config.method,
          message: err?.message,
          status: err?.status,
          isNetworkError: err?.isNetworkError,
        })
      }
      // 如果请求被取消或是网络中断等，直接抛出 normalized error
      const isCancel = axios.isCancel(err) || err?.isCancel;
      if (isCancel) throw err;

      // 处理重试（只对幂等请求生效）
      const method = (config.method || "get").toLowerCase();
      const idempotent = ["get", "head", "options"].includes(method);
      const shouldRetry =
        typeof config.retryOn === "function"
          ? config.retryOn(err)
          : idempotent && attempt <= (config.retry ?? 0);

      if (shouldRetry) {
        // 指数退避 (exponential backoff)
        const delay = (config.retryDelay ?? 300) * Math.pow(2, attempt - 1);
        await sleep(delay);
        continue; // 再试一次
      }

      // 非重试：抛出错误（已 normalize）
      throw err;
    }
  }
}
